{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "71174a9f",
   "metadata": {},
   "outputs": [],
   "source": [
    "#| default_exp vad"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1bb61c7c",
   "metadata": {},
   "source": [
    "# Perform Voice Activity Detection (VAD)\n",
    "\n",
    "We want to start with voice activity detection to make sure we are not cutting off words and sentences in the middle.\n",
    "This should improve transcription reliability and make both the quantization and T2S model training easier.\n",
    "\n",
    "**Usage:**  \n",
    "```\n",
    "python -m whisperspeech.vad https://huggingface.co/datasets/collabora/librilight-webdataset/resolve/main/librilight-large-wo6454-flac-000002.tar\n",
    "```\n",
    "\n",
    "You can pass in either a URL or a local file name. The result will go into a file in the current directory named after the source file but replacing `flac` with `vad` (check the `flac_to_vad_name` function)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c9ffbdc3",
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "22ed2d09",
   "metadata": {},
   "outputs": [],
   "source": [
    "#| exporti\n",
    "import os\n",
    "import torch\n",
    "import torchaudio\n",
    "\n",
    "from pathlib import Path\n",
    "from fastprogress import progress_bar\n",
    "from fastcore.script import call_parse\n",
    "\n",
    "import whisperx\n",
    "import random\n",
    "import numpy as np\n",
    "import webdataset as wds"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bc6b2da0",
   "metadata": {},
   "outputs": [],
   "source": [
    "from IPython.display import HTML\n",
    "import pylab as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8d80783a",
   "metadata": {},
   "outputs": [],
   "source": [
    "#| exporti\n",
    "# some of the original file names have a dot in their name\n",
    "# webdataset does not like it so let's patch it\n",
    "def fix_dots_in_names(name):\n",
    "    name, ext = name.rsplit('.', 1)\n",
    "    return \".\".join((name.replace('.', '_'), ext))\n",
    "\n",
    "def load_dataset(url, decode=True, rename_files=None):\n",
    "    ds = wds.WebDataset(url, rename_files=rename_files)\n",
    "    if not decode: return ds\n",
    "    return ds.decode(wds.torch_audio)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "714048d3",
   "metadata": {},
   "source": [
    "We use the voice activity detection model from WhisperX (but we don't use their merging algorithm):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "805e1bbd",
   "metadata": {},
   "outputs": [],
   "source": [
    "#| exporti\n",
    "def extract_segments(vad_result, max_duration):\n",
    "    binarize = whisperx.vad.Binarize(max_duration=max_duration)\n",
    "    segments = binarize(vad_result)\n",
    "    return [(x.start, x.end) for x in segments.get_timeline()]\n",
    "\n",
    "def segment_audio(vad_model, audio, sr=16000):\n",
    "    vad_result = vad_model({\"waveform\": audio, \"sample_rate\": sr})\n",
    "    return extract_segments(vad_result, 30)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c33f2559",
   "metadata": {},
   "source": [
    "Test just a few files:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f23ee98d",
   "metadata": {},
   "outputs": [],
   "source": [
    "ds = wds.WebDataset('/data2/libritts-r-raw-000000.tar').compose(wds.decode(wds.torch_audio))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b0ad90d7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'__key__': './dev-clean/1272/128104/1272_128104_000001_000000',\n",
       " '__url__': '/data2/libritts-r-raw-000000.tar',\n",
       " 'normalized.txt': \"A 'JOLLY' ART CRITIC\",\n",
       " 'original.txt': \"A 'JOLLY' ART CRITIC\",\n",
       " 'wav': (tensor([[ 0.0000,  0.0000,  0.0000,  ..., -0.0036, -0.0038, -0.0050]]),\n",
       "  24000)}"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "for x in ds: break\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "249b6ec6",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Lightning automatically upgraded your loaded checkpoint from v1.5.4 to v2.0.2. To apply the upgrade to your files permanently, run `python -m pytorch_lightning.utilities.upgrade_checkpoint --file ../../../.cache/torch/whisperx-vad-segmentation.bin`\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model was trained with pyannote.audio 0.0.1, yours is 2.1.1. Bad things might happen unless you revert pyannote.audio to 0.x.\n",
      "Model was trained with torch 1.10.0+cu102, yours is 2.0.1+cu118. Bad things might happen unless you revert torch to 1.x.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='10' class='' max='10' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [10/10 00:10&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-rw-r--r-- 1 root root 7.5K Sep 21 08:51 librilight-large-wo6454-vad-000002.tar.gz\n",
      "large/10089/five_minutes_stories_1508_librivox_64kb_mp3/5minutesstories_03_molesworth_64kb.vad.npy\n",
      "large/10089/five_minutes_stories_1508_librivox_64kb_mp3/5minutesstories_04_molesworth_64kb.vad.npy\n",
      "large/10089/five_minutes_stories_1508_librivox_64kb_mp3/5minutesstories_08_molesworth_64kb.vad.npy\n",
      "large/10089/five_minutes_stories_1508_librivox_64kb_mp3/5minutesstories_09_molesworth_64kb.vad.npy\n",
      "large/10089/five_minutes_stories_1508_librivox_64kb_mp3/5minutesstories_10_molesworth_64kb.vad.npy\n",
      "large/10089/five_minutes_stories_1508_librivox_64kb_mp3/5minutesstories_11_molesworth_64kb.vad.npy\n",
      "large/10089/goodcheerstories_1511_librivox_64kb_mp3/goodcheerstories_13_dickinson_64kb.vad.npy\n",
      "large/10089/goodcheerstories_1511_librivox_64kb_mp3/goodcheerstories_30_dickinson_64kb.vad.npy\n",
      "large/10089/mothers_nursery_tales_1512_librivox_64kb_mp3/mothers_nursery_tales_16_pyle_64kb.vad.npy\n",
      "large/10089/mothers_nursery_tales_1512_librivox_64kb_mp3/mothers_nursery_tales_25_pyle_64kb.vad.npy\n"
     ]
    }
   ],
   "source": [
    "# test it locally\n",
    "input:str  = 'https://huggingface.co/datasets/collabora/librilight-webdataset/resolve/main/librilight-large-wo6454-flac-000002.tar'\n",
    "output:str = input.rsplit(\"/\", 1)[1].replace('flac', 'vad') + \".gz\"\n",
    "\n",
    "ds = load_dataset(input)\n",
    "vad_model = whisperx.vad.load_vad_model('cuda')\n",
    "\n",
    "with wds.TarWriter(output) as sink:\n",
    "    for s in progress_bar(ds, total=10):\n",
    "        audio, sr = s['flac']\n",
    "        assert(sr == 16000)\n",
    "        sink.write({\n",
    "            \"__key__\": s['__key__'],\n",
    "            \"vad.npy\": np.array(segment_audio(vad_model, audio), dtype=np.float16)\n",
    "        })\n",
    "        \n",
    "!ls -lh {output}\n",
    "!tar tf {output}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9110f217",
   "metadata": {},
   "source": [
    "## Batch processing\n",
    "\n",
    "Let's put everything above together."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "86cada0e",
   "metadata": {},
   "outputs": [],
   "source": [
    "#| exporti\n",
    "def flac_to_vad_name(input):\n",
    "    if '-flac-' in input:\n",
    "        return input.rsplit(\"/\", 1)[1].replace('flac', 'vad') + \".gz\"\n",
    "    else:\n",
    "        return input.rsplit(\"/\", 1)[1].replace('raw', 'vad') + \".gz\"\n",
    "\n",
    "@call_parse\n",
    "def process_shard(\n",
    "    input:str,           # input shard URL/path\n",
    "    output:str=None,     # output shard URL/path\n",
    "    fix_dots:bool=False, # fix dots in LibriLight filenames\n",
    "):\n",
    "    if output is None: output = flac_to_vad_name(input)\n",
    "    \n",
    "    ds = torch.utils.data.DataLoader(load_dataset(input, rename_files=fix_dots_in_names if fix_dots else None), num_workers=2, batch_size=None)\n",
    "    vad_model = whisperx.vad.load_vad_model('cuda')\n",
    "    \n",
    "    tmp = output+\".tmp\"\n",
    "    with wds.TarWriter(tmp) as sink:\n",
    "        for s in progress_bar(ds, total='noinfer'):\n",
    "            audio, sr = s.get('flac', s.get('wav', (None, None)))\n",
    "            if audio is None:\n",
    "                print(f\"warning: '{s['__key__']}' does not contain an audio file\")\n",
    "                continue\n",
    "            sink.write({\n",
    "                \"__key__\": s['__key__'],\n",
    "                \"vad.npy\": np.array(segment_audio(vad_model, audio, sr=sr), dtype=np.float16)\n",
    "            })\n",
    "    os.rename(tmp, output)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "22c6af11",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Lightning automatically upgraded your loaded checkpoint from v1.5.4 to v2.0.2. To apply the upgrade to your files permanently, run `python -m pytorch_lightning.utilities.upgrade_checkpoint --file ../../../.cache/torch/whisperx-vad-segmentation.bin`\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model was trained with pyannote.audio 0.0.1, yours is 2.1.1. Bad things might happen unless you revert pyannote.audio to 0.x.\n",
      "Model was trained with torch 1.10.0+cu102, yours is 2.0.1+cu118. Bad things might happen unless you revert torch to 1.x.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='335' class='' max='335' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [335/335 03:30&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# for reference, this was the performance on a single 4090:\n",
    "process_shard('https://huggingface.co/datasets/collabora/librilight-webdataset/resolve/main/librilight-small-flac-000000.tar', fix_dots=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3b23c50c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['.', 'dev-clean', '1272', '128104', '1272_128104_000001_000000']"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "for x in wds.WebDataset('/data2/libritts-r-vad-000000.tar').decode(): break\n",
    "x['__key__'].split('/')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a6a6ca7f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([1.6967e+04, 0.0000e+00, 6.4500e+02, 0.0000e+00, 0.0000e+00,\n",
       "        1.0800e+02, 0.0000e+00, 2.5000e+01, 0.0000e+00, 7.0000e+00]),\n",
       " array([1. , 1.4, 1.8, 2.2, 2.6, 3. , 3.4, 3.8, 4.2, 4.6, 5. ]),\n",
       " <BarContainer object of 10 artists>)"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist([x['vad.npy'].shape[0] for x in wds.WebDataset('/data2/libritts-r-vad-000000.tar').decode()])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "076741b9",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "python3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
